package com.aegis.manage.utils;

import cn.hutool.core.codec.Base62;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import org.apache.commons.codec.digest.HmacUtils;


import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Locale;
import java.util.Optional;
import java.util.UUID;

/**
 * @Author renogo
 *
 * @Version 1.0
 */
public class PasswordUtil {

    /**
     * 加密密码
     *
     * @param rawPwd    未加密的密码
     * @param publicKey 公钥
     * @return
     */
    public static String rsaEncrypt(String rawPwd, String publicKey) {
        RSA rsa = new RSA(null, publicKey);
        return rsa.encryptHex(rawPwd.getBytes(Charset.defaultCharset()), KeyType.PublicKey);
    }


    /**
     * 生成一个入库的密码
     *
     * @param rsaPwd     RSA公钥加密后的密码,hex格式，不要base64
     * @param privateKey
     * @param salt
     * @return 返回一个可以入库的密码
     */
    public static String getPasswordInDb(String rsaPwd, String privateKey, String salt) {
        String rawPassword = rsaDecrypt(rsaPwd, privateKey);
        String password = PasswordUtil.md5(rawPassword, salt);
        return password;
    }


    /**
     * 解密密码
     *
     * @param rsaPwd     hex格式，不要base64
     * @param privateKey
     * @return 返回明文密码
     */
    public static String rsaDecrypt(String rsaPwd, String privateKey) {
        RSA rsa = new RSA(privateKey, null);
        byte[] decrypt = rsa.decrypt(HexUtil.decodeHex(rsaPwd), KeyType.PrivateKey);
        String rawPwd = new String(decrypt, Charset.defaultCharset());
        return rawPwd;
    }

    /**
     * 对密码进行摘要计算
     *
     * @param rawPwd 明文密码
     * @param salt
     * @return 返回可以入库的密码
     */
    public static String md5(String rawPwd, String salt) {
        salt = Optional.ofNullable(salt).orElse("");
        return SecureUtil.md5(rawPwd + salt);
    }


    /**
     * @param n
     * @param t
     * @return
     */
    public static boolean matches(String n, String t, String salt) {
        return md5(n, salt).equals(t);
    }


    /**
     * @return
     */
    public static String generateAppId() {
        // 雪花算法改进：41位时间戳 + 10位机器ID + 12位序列号（可定制业务前缀）
        long id = IdUtil.getSnowflake().nextId();
        // 添加业务前缀（如APP），并转换为Base62缩短长度[4,6](@ref)
        return Base62.encode(id + " ").toLowerCase(Locale.ROOT);
    }


    /**
     * @return
     */
    public static String generateAppSecret() {
        // 高强度随机数（128位） + 时间戳 + HMAC签名[7,8](@ref)
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[16];
        random.nextBytes(salt);

        String rawSecret = UUID.randomUUID().toString() + System.currentTimeMillis();
        return HmacUtils.hmacSha256Hex(
                Base64.getEncoder().encodeToString(salt),
                rawSecret
        );
    }


}
